% BEGIN LICENSE BLOCK
% Version: CMPL 1.1
%
% The contents of this file are subject to the Cisco-style Mozilla Public
% License Version 1.1 (the "License"); you may not use this file except
% in compliance with the License.  You may obtain a copy of the License
% at www.eclipse-clp.org/license.
% 
% Software distributed under the License is distributed on an "AS IS"
% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
% the License for the specific language governing rights and limitations
% under the License. 
% 
% The Original Code is  The ECLiPSe Constraint Logic Programming System. 
% The Initial Developer of the Original Code is  Cisco Systems, Inc. 
% Portions created by the Initial Developer are
% Copyright (C) 1996 - 2006 Cisco Systems, Inc.  All Rights Reserved.
% 
% Contributor(s): 
% 
% END LICENSE BLOCK

% @(#)extmeta.tex	1.8 96/01/08 
%

\chapter{Attributed Variables}
%HEVEA\cutdef[1]{section}
\label{attrvars}
\label{metaterms}
\index{attributed variables|(}

\section{Introduction}
The {\em attributed variable} is a special \eclipse data type which
represents a variable together with attached attributes.
In the literature, attributed variables are sometimes referred to as
\index{metaterms}
``metaterms''. 
The name {\em metaterm} originates from its application in meta-programming:
for an object-level program, a metaterm looks like a variable, but for
a meta-program the same variable is just a piece of data which, possibly
together with additional meta-level information, forms the metaterm.

The attributed variable is a powerful means to implement various extensions of the
plain Prolog language.
In particular, it allows the system's behaviour
on unification to be customised.
In most situations, an attributed variable behaves like a normal
variable.
E.g.\ it can be unified with other terms and \bipref{var/1}{../bips/kernel/typetest/var-1.html} succeeds on it.
The differences compared to a plain variable are:
\begin{itemize}
\item an attributed variable has a number of associated {\it attributes}
\item the attributes are included in the module system
\item when an attributed variable occurs in the unification and in some
built-in predicates, each attribute is processed by a user-defined
{\it handler}
\end{itemize}

\section{Declaration}
An attributed variable can have any number of attributes.
The attributes are accessed by their name.
Before an attribute can be created and used, it must be declared
with the predicate \bipref{meta_attribute/2}{../bips/kernel/termmanip/meta_attribute-2.html}.
The declaration has the format
\begin{quote}
{\bf meta_attribute(Name, HandlerList)}
\end{quote}
{\bf Name} is an atom denoting the attribute name
and usually it is the name of the module where this attribute
is being created and used.
{\bf HandlerList} is a (possibly empty) list of handler specifications
for this attribute (see Section \ref{metahandlers}).

\section{Syntax}

{\samepage
The most general attributed variable syntax is
\begin{quote}
$Var\{Name_1:Attr_1, Name_2:Attr_2, \ldots, Name_n:Attr_n\}$
\end{quote}
where the syntax of {\it Var} is like that of a variable,
{\it $Name_i$}
are attribute names and
{\it $Attr_i$}
are the values of the corresponding attributes.
}
The expression {\bf Var\{Attr\}} is a shorthand for {\bf Var\{Module:Attr\}}
where {\bf Module} is the current module name.
The former is called {\it unqualified} and the latter {\it qualified}
attribute specification.
\index{qualified attribute specification}
\index{attribute!specification!qualified}
\index{attribute!specification!unqualified}
As the attribute name is usually identical with the source module name,
all occurrences of an attributed variable in the source module may use the unqualified
specification.

If there are several occurrences of the same attributed variable in a single term,
only one occurrence is written with the attribute,
the others just refer to the variable's name,
e.g.
\begin{quote}\begin{verbatim}
p(X, X{attr:Attr})
\end{verbatim}\end{quote}
or
\begin{quote}\begin{verbatim}
p(X{attr:Attr}, X)
\end{verbatim}\end{quote}
both describe the same term, which has two occurrences of a single attributed variable
with attribute {\tt attr:Attr}.
The following is a syntax error (even when the attributes are identical):
\begin{quote}\begin{verbatim}
p(X{attr:Attr}, X{attr:Attr})
\end{verbatim}\end{quote}


\section{Creating Attributed Variables}
A new attribute can be added to a variable
using the tool predicate
\begin{quote}
{\bf add_attribute(Var, Attr)}.
\end{quote}
\index{add_attribute/2}
An attribute whose name is not the current module name
can be added using \bipref{add_attribute/3}{../bips/kernel/termmanip/add_attribute-3.html} which is its tool
body predicate (exported in {\tt sepia_kernel}).
If {\bf Var} is a free variable, it will be bound to a new attributed variable
whose attribute corresponding to the current module is
{\bf Attr} and all its other attributes are free variables.
If {\bf Var} is already an attributed variable and its attribute is uninstantiated,
it will be bound to {\bf Attr}, otherwise the effect of this predicate
will be the same as unifying {\bf Var} with another attributed variable
whose attribute corresponding to the current module is 
{\bf Attr}.

\section{Decomposing Attributed Variables}
The attributes of an attributed variable can be accessed using one-way
unification in a matching clause, e.g.
\begin{quote}
\begin{verbatim}
    get_attribute(X{Name:Attribute}, A) :-
        -?->
        A = Attribute.
\end{verbatim}
\end{quote}
This clause succeeds only when the first argument is an attributed variable,
and it binds
{\tt X} to the whole attributed variable and {\tt A} to the attribute
with name {\tt Name}.
Note that a normal (unification) clause can {\bf not} be used to decompose
an attributed variable (it would create a new attributed variable and unify this with the caller
argument, but the unification is handled by an attributed variable handler, see
Section \ref{metahandlers}).

\section{Attribute Modification}
Often an extension needs to modify the data stored in the
attribute to reflect changes in the computation.
The usual Prolog way to do this is by reserving
one argument in the attribute structure for this next value.
before accessing the most recent attribute value this chain
of values has to be dereferenced until a value is found whose
link is still free.
A perfect compiler should be able to detect that the older
attribute values are no longer accessed and it would compile
these modifications using destructive assignment.
Current compilers are unfortunately not able to perform
this optimization (some systems can reduce these chains
during garbage collection, but until this occurs,
the list has to be dereferenced for each access and update).
To avoid performance loss for both attribute updating and
access, {\eclipse} provides a predicate for explicit
attribute update: 
{\bf setarg(I, Term, NewArg)} will update the {\bf I}'th
argument of {\bf Term} to be {\bf NewArg}.
Its previous value will be restored on backtracking.
%Although the use of this predicate does not corrupt the
%declarative reading of the program (it is merely
%a shorthad for the above described modification
%using value links), we still recommed to use it with care,
%because sometimes it might yield unexpected results.

Libraries which define user-programmable extensions
like e.g. {\bf fd.pl} usually define predicates that
modify the attribute or a part of it, so that an explicit
use of the \bipref{setarg/3}{../bips/kernel/termmanip/setarg-3.html} predicate is not necessary.

\section{Attributed Variable Handlers}
\label{metahandlers}
An attributed variable is a variable with some additional information
which is ignored by ordinary {\it object level} system predicates.
{\it Meta level} operations on attributed variables are handled by
extensions which know
the contents of their attributes and can specify the outcome
of each operation.
This mechanism is implemented using {\it attributed variable handlers},
\index{attributed variables!handlers}
which are user-defined predicates invoked
whenever an attributed variable occurs in one of the predefined
operations.
The handlers are specified in the attribute declaration
{\bf meta_attribute(Name, HandlerList)}, the second argument
is a list of handlers in the form
\begin{quote}
\begin{verbatim}
[unify:UnifyHandler, test_unify:TUHandler, ...]
\end{verbatim}
\end{quote}
Handlers for operations which are not specified or those that are
\bipref{true/0}{../bips/kernel/control/true-0.html} are ignored and never invoked.
If {\bf Name} is an existing extension, the specified handlers
replace the current ones.

Whenever one of the specified operations detects an attributed variable,
it will invoke all handlers that were declared for it
and each of them receives either the whole attributed variable
or its particular attribute as argument.
The system does not check if the attribute that corresponds
to a given handler is instantiated or not; this means
that the handler must check itself if the attributed variable
contains any attribute information or not.
For instance, if an attributed variable {\it X\{a:_, b:_, c:f(a)\}}
is unified with the attributed variable {\it Y\{a:_, b:_, c:f(b)\}},
the handlers for the attributes {\it a} and {\it b} should
treat this as binding of two plain variables
because their attributes were not involved.
Only the handler for {\it c} has any work to do here.
The library {\bf suspend.pl} can be used as a template
\index{library!suspend.pl}
for writing attributed variable handlers.

The following operations invoke attributed variable handlers:

\begin{itemize}
%--------------------------
\item {\bf unify}: the usual unification.
\index{unify handler}
The handler procedure is
\begin{quote}
unify_handler(+Term, ?Attribute [,SuspAttr])
\end{quote}
The first argument is the term that was unified with the attributed variable,
it is either a nonvariable or an attributed variable.
The second argument is directly the contents of the attribute slot
corresponding to the extension, i.e. it is not the whole attributed variable.
When this handler is invoked, the attributed variable is already bound
to {\it Term}.
The optional third argument is the suspend-attribute of the former
variable; it may be needed to wake the variable's 'constrained' suspension
list.

If an attributed variable is unified with a standard variable, the variable is bound
to the attributed variable and no handlers are invoked.
If an attributed variable is unified with another attributed variable or a non-variable,
the attributed variable is bound (like a standard variable) to the other term
{\bf and} all handlers for the {\bf unify} operation are invoked. 
Note that several attributed variable bindings can occur e.g.\ during a head unification
and also during a single unification of compound terms.
The handlers are only invoked at certain trigger points (usually before the
next predicate call).

%--------------------------
\item {\bf test_unify}: the unification which is not supposed
\index{test_unify handler}
to trigger constraints propagation, it is used e.g.
in the \bipref{not_unify/2}{../bips/kernel/termcomp/not_unify-2.html}
predicate.
The handler procedure is
\begin{quote}
test_unify_handler(+Term, ?Attribute)
\end{quote}
where the arguments are the same as for the unify handler.
During the execution of the handler the attributed variable is bound
to {\it Term}, however when all local handlers succeed,
all bindings are undone.

\item {\bf compare_instances}: computation of instance, subsumption
\index{compare_instances handler}
and variance relationship, as performed by the built-ins
\bipref{instance/2}{../bips/kernel/termcomp/instance-2.html} and
\bipref{variant/2}{../bips/kernel/termcomp/variant-2.html}.
The handler procedure is
\begin{quote}
instance_handler(-Res, ?TermL, ?TermR)
\end{quote}
and its arguments are similar to the ones of the
\bipref{compare_instances/3}{../bips/kernel/termcomp/compare_instances-3.html}
predicate.
The handler is invoked with one or both of {\it TermL} and {\it TermR} being
attributed variables. The task of the handler is to compare the two terms
and instantiate {\bf Res} to either $=$ (if the terms are variants) or $<$
(if {\it TermL} is a proper instance of {\it TermR}). If the terms are
incomparable, the handler should fail. If {\it TermR} is proper instance
of {\it TermL}, the handler should either return $>$ or fail.
All bindings made in the handler will be undone after processing
the local handlers.

\item {\bf copy_term}: the handler is invoked when terms are copied by the
\index{copy_term handler}
\bipref{copy_term/2}{../bips/kernel/termmanip/copy_term-2.html} or
\bipref{copy_term_vars/3}{../bips/kernel/termmanip/copy_term_vars-3.html} built-ins.
The handler procedure is
\begin{quote}
copy_handler(?AttrVar, ?Copy)
\end{quote}
{\it AttrVar} is the attributed variable encountered in the
copied term, {\it Copy} is its corresponding variable in the copy.
All extension handlers receive the same arguments.
This means that if the attributed variable should be copied as
an attributed variable, the handler must check if {\it Copy} is still
a free variable or if it was already bound to an attributed variable by a previous handler.

\item {\bf suspensions}: this handler is invoked by the
\index{suspensions handler}
\bipref{suspensions/2}{../bips/kernel/suspensions/suspensions-2.html} predicate
to collect all the suspension lists inside the attribute.
The handler call pattern is
\begin{quote}
suspensions_handler(?AttrVar, -ListOfSuspLists, -Tail)
\end{quote}
{\it AttrVar} is an attributed variable. The handler should bind
{\it ListOfSuspLists} to a list containing all the attribute's
suspension lists and ending with {\it Tail}.


\item {\bf delayed_goals_number}: handler is invoked by the
\index{delayed_goals_number handler}
\bipref{delayed_goals_number/2}{../bips/kernel/suspensions/delayed_goals_number-2.html}
predicate.
The handler call pattern is
\begin{quote}
delayed_goals_number_handler(?AttrVar, -Number)
\end{quote}
{\it AttrVar} is the attributed variable encountered in the
term, {\it Number} is the number of delayed
goals occurring in this attribute.
Its main purpose is for the first-fail selection predicates,
i.e. it should return the number of constraints imposed on
the variable.

\item {\bf get_bounds}:
\index{get_bounds handler}
    This handler is used by the predicate
    \bipref{get_var_bounds/3}{../bips/kernel/termmanip/get_var_bounds-3.html}
    to retrieve information about the lower and upper bound of a numeric
    variable. 
    The handler should therefore only be defined if the attribute contains
    that kind of information. The handler call pattern is
    \begin{quote}
    get_bounds_handler(?AttrVar, -Lwb, -Upb)
    \end{quote}
    The handler is only invoked if the variable has the corresponding
    (non-empty) attribute.
    The handler should bind {\it Lwb} and {\it Upb} to numbers
    (any numeric type) reflecting the attribute's information about lower
    and upper bound of the variable, respectively.
    If different attributes return different bounds information,
    \bipref{get_var_bounds/3}{../bips/kernel/termmanip/get_var_bounds-3.html}
    will return the intersection of these bounds. This can be empty (Lwb $>$ Upb).
 
\item {\bf set_bounds}:
\index{set_bounds handler}
    This handler is used by the predicate
    \bipref{set_var_bounds/3}{../bips/kernel/termmanip/set_var_bounds-3.html}
    to distribute information about the lower and upper bound of a numeric
    variable to all its existing attributes. 
    The handler should therefore only be defined if the attribute can
    incorporate this kind of information. The handler call pattern is
    \begin{quote}
    set_bounds_handler(?AttrVar, +Lwb, +Upb)
    \end{quote}
    The handler is only invoked if the variable has the corresponding
    (non-empty) attribute.
    {\it Lwb} and {\it Upb} are the numbers that were passed to
    \bipref{set_var_bounds/3}{../bips/kernel/termmanip/set_var_bounds-3.html}, and the handler is expected to update its
    own bounds representation accordingly.



\item {\bf print}: attribute printing in
\index{print handler}
\bipref{write/1,2}{../bips/kernel/ioterm/write-1.html},
\bipref{writeln/1,2}{../bips/kernel/ioterm/writeln-1.html},
\bipref{printf/2,3}{../bips/kernel/ioterm/printf-2.html}
when the {\bf m} option is specified.
The handler procedure is
\begin{quote}
print_handler(?AttrVar, -Attribute)
\end{quote}
{\it AttrVar} is the attributed variable being printed, {\it Attribute}
is the term which will be printed as a value for this attribute,
prefixed by the attribute name.
If no handler is specified for an attribute, or the print handler fails, 
the attribute will not be printed.

\end{itemize}

The following handlers are still supported for compatibility,
but their use is not recommened:
\begin{itemize}
\item {\bf pre_unify}: this is another handler which can be invoked on
\index{pre_unify handler}
normal unification, but it is called {\it before} the unification
itself occurs.
The handler procedure is
\begin{quote}
pre_unify_handler(?AttrVar, +Term)
\end{quote}
The first argument is the attributed variable to be unfied,
the second argument is the term it is going to be unified with.
This handler is provided only for compatibility with SICStus Prolog
and its use is not recommended, because it is less efficient
than the {\bf unify} handler and because its semantics is somewhat
unclear, there may be cases where changes inside this handler
may have unexpected effects.

\item {\bf delayed_goals}: this handler is superseded by the
\index{delayed_goals handler}
suspensions-handler, which should be preferred. If there is no suspensions-
handler, this handler is invoked by the obsolete
\bipref{delayed_goals/2}{../bips/kernel/suspensions/delayed_goals-2.html} predicate.
The handler procedure is
\begin{quote}
delayed_goals_handler(?AttrVar, ?GoalList, -GoalCont)
\end{quote}
{\it AttrVar} is the attributed variable encountered in the
term, {\it GoalList} is an open-ended list of all delayed
goals in this attribute and {\it GoalCont} is the
tail of this list.

\end{itemize}

%--------------------------
\subsection{Printing Attributed Variables}
\index{output_mode}
\index{printf/2}
The different output predicates treat attributed variables differently.
The \bipref{write/1}{../bips/kernel/ioterm/write-1.html} predicate prints
the attributes using the print-handlers,
while \bipref{writeq/1}{../bips/kernel/ioterm/writeq-1.html} prints the whole attribute, so that the attributed variable
can be read back.
The \bipref{printf/2}{../bips/kernel/ioterm/printf-2.html} predicate has two options to be combined with
the {\bf w} format: {\bf M} forces the whole attributed variable to be printed
together with all its attributes in the standard format, so that
it can be read back in.
With the {\bf m} option the attributed variable is printed using the handlers
defined for the {\bf print} operation.
If there is only one handled attribute, the attributed variable is printed as
\begin{quote}
X\{Attr\}
\end{quote}
where {\it Attr} is the value obtained from the handler.
If there are several handled attributes, all attributes are qualified
like in
\begin{quote}
X\{a:A, b:B, c:C\}.
\end{quote}
{\samepage
An attributed variable {\tt X\{m:a\}} with {\bf print} handler {\bf =/2}
can thus be printed in different ways, e.g.:
\footnote{The attribute {\bf suspend} is always present and defined
by system coroutining.}
\begin{quote}\begin{verbatim}
printf("%w", [X{m:a}])   or write(X{m:a}):    X   
printf("%vMw", [X{m:a}]) or writeq(X{m:a}):   _g246{suspend : _g242, m : a}
printf("%mw", [X{m:a}]):                      X{a}
printf("%Mw", [X{m:a}]):                      X{suspend : _g251, m : a}
printf("%Vmw", [X{m:a}]):                     X_g252{a}
\end{verbatim}\end{quote}
}

\index{macro!write}
Write macros for attributed variables are not allowed because one extension alone
should not decide whether the other attributes will be printed or not.

\section{Built-Ins and Attributed Variables}
%\begin{description}
\begin{description}
\index{free/1}
\item[free(?Term)]
%\item[free(?Term)]
This type-checking predicate succeeds iff its argument is an
ordinary free variable, it fails if it is an attributed variable.

\index{meta/1}
%\item[meta(?Term)]
\item[meta(?Term)]
This type-checking predicate succeeds iff its argument is an attributed variable.
For other type testing predicates an attributed variable behaves like a variable.

%\end{description}
\end{description}

\section{Examples of Using Attributed Variables}
\subsection{Variables with Enumerated Domains}
As an example, let us implement variables of enumerable types
using attributes.
We choose to represent these variable as attributed variables
whose attribute is
a enum/1 structure with a list holding the values the variable may take,
e.g.
\begin{quote}\begin{verbatim}
X{enum([a,b,c])}
\end{verbatim}\end{quote}

We have to specify now what should happen when such a variable is
bound. This is done by writing a handler for the {\bf unify} operation.
The predicate unify_enum/2 defined below is this
handler.
Its first argument is the value that the attributed variable has been bound to,
the second is the attribute that the bound attributed variable had
(keep in mind that the system has already bound the attributed variable to the
new value).  We distinguish two cases:

First, the attributed variable has been
bound to another attributed variable (1st clause of unify_enum/2).
In this case, we form the intersection between the two lists
of admissible values. If it is empty, we fail.
If it contains exactly one value, we can instantiate the remaining
attributed variable with this value.
Otherwise, we bind it to a new attributed variable whose attribute represents
the remaining admissible values.

Second, when the attributed variable has been bound to a non-variable, the
task that remains for the handler is merely to check if this binding
was admissible (2nd clause of unify_enum/2).

\begin{quote}\begin{verbatim}
[eclipse 2]: module(enum).
warning: creating a new module in module(enum)
[enum 3]: [user].
:- meta_attribute(enum, [unify:unify_enum/2, print:print_enum/2]).
:- import setarg/3 from sepia_kernel.

% unify_enum(+Term, Attribute)
unify_enum(_, Attr) :-
    /*** ANY + VAR ***/
    var(Attr).                  % Ignore if no attribute for this extension
unify_enum(Term, Attr) :-
    compound(Attr),
    unify_term_enum(Term, Attr).

unify_term_enum(Value, enum(ListY)) :-
    nonvar(Value),               % The attributed variable was instantiated
    /*** NONVAR + META ***/
    memberchk(Value, ListY).
unify_term_enum(Y{AttrY}, AttrX) :-
    -?->
    unify_enum_enum(Y, AttrX, AttrY).

unify_enum_enum(_, AttrX, AttrY) :-
    var(AttrY),                         % no attribute for this extension
    /*** VAR + META ***/
    AttrX = AttrY.                      % share the attribute
unify_enum_enum(Y, enum(ListX), AttrY) :-
    nonvar(AttrY),
    /*** META + META ***/
    AttrY = enum(ListY),
     intersection(ListX, ListY, ListXY),
     ( ListXY = [Val] ->
            Y = Val
     ;   
            ListXY \= [],
            setarg(1, AttrY, ListXY)
     ).  

print_enum(enum(List), Attr) :-
    -?->
    Attr = List.
 user       compiled traceable 1188 bytes in 0.03 seconds

yes.
[enum 4]: A{enum([yellow, blue, white, green])}
                = B{enum([orange, blue, red, yellow])}.

A = B = A{[blue, yellow]}
yes.
[enum 5]: A{enum([yellow, blue, white, green])}
                = B{enum([orange, blue, red, black])}.

A = B = blue
yes.
[enum 6]: A{enum([yellow, blue, white, green])} = white.

A = white
yes.
[enum 7]: A{enum([yellow, blue, white, green])} = red.

no (more) solution.

\end{verbatim}
\end{quote}

Some further remarks on this code:
\index{matching}
\index{pattern matching}
\index{unification!pattern matching}
The second clause of {\bf unify_term_enum/2}
is a {\bf matching clause}, as indicated
by the ${\bf -?->}$ guard.
A matching clause is the only way to decompose an attributed variable.
Note that this clause matches only calls that have an attributed variable
with nonempty {\bf enum} attribute on the
first argument position.


\section{Attribute Specification}
The structures notation (see section~\ref{chapstruct})
is used to define
and access variable attributes and their arguments.
This makes the code independent of the number of attributes
and positions of their arguments.
Wherever appropriate, the libraries described in this document
describe their attributes in this way, e.g.
\begin{quote}
${\bf suspend\{inst:I, constrained:C, bound:B\}}$
\end{quote}
says that the structure name is {\bf suspend} and that
it has (at least) three arguments with the corresponding names.


\index{attributed variables|)}

%HEVEA\cutend


